using System;
using System.Collections.Generic;
using System.Text;

using SlimDX;
using SlimDX.Direct3D9;

using miciv;
using micivCore.Data;
using micivCore.Level;
using miciv.Rendering;
using micivCore.Faction;

namespace micivCore
{
    public class Module : IModule
    {
        protected CoreContext m_coreContext;
        protected LevelManager m_levelManager;
        protected MapTileManager m_mapTileManager;
        protected IRendererContext m_rendererContext;
        protected FactionManager m_factionManager;

        protected List<IRendererContext> m_lstRendererContextes;
        public List<IRendererContext> RestrictedRendererContextes
        {
            get
            {
                return this.m_lstRendererContextes;
            }
        }

        public Module(CoreContext _coreContext)
        {
            this.m_coreContext = _coreContext;
        }

        protected bool ProcessCommand(Command _command)
        {
            if ("LoadLevel" == _command.Name)
            {
                if ((null == _command.Args)
                    || (2 != _command.Args.Length)
                    || (typeof(string) != _command.Args[0].GetType())
                    || (typeof(string) != _command.Args[1].GetType()))
                {
                    System.Diagnostics.Debug.WriteLine("{0} : too few/many argument and/or bad level name and/or bad nickname argument (string type excpected).", _command.Name);
                    return false;
                }
                // load level
                this.m_levelManager.SetLocalPlayerNickname(_command.Args[1] as string);
                _command.Result = this.m_levelManager.LoadLevel(_command.Args[0] as string);
                if (null != _command.Result)
                {
                    // level successfully : load various related ui
                    IUIManager uiManager = this.m_coreContext.GetData<IUIManager>("UIManager");
                    uiManager.LoadScene("unittechniqueselection.xml");
                    return true;
                }
                return false;
            }
            if ("UnloadLevel" == _command.Name)
            {
                if ((1 != _command.Args.Length) || (typeof(string) != _command.Args[0].GetType()))
                {
                    System.Diagnostics.Debug.WriteLine("{0} : too few/many argument or bad level name argument (string type excpected).", _command.Name);
                    return false;
                }
                // unload level associated ui
                IUIManager uiManager = this.m_coreContext.GetData<IUIManager>("UIManager");
                uiManager.UnloadScene("unittechniqueselection.xml");
                // unload level
                this.m_levelManager.UnloadLevel(_command.Args[0] as string);
                return true;
            }
            if ("UpdateLevel" == _command.Name)
            {
                if ((null == _command.Args)
                    || (2 != _command.Args.Length)
                    || (typeof(Level.Level) != _command.Args[0].GetType())
                    || (typeof(float) != _command.Args[1].GetType()))
                {
                    System.Diagnostics.Debug.WriteLine("{0} : too few/many argument or bad level argument (Level type excpected).", _command.Name);
                    return false;
                }
                Level.Level level = _command.Args[0] as Level.Level;
                level.Update((float)_command.Args[1]);
                return true;
            }
            if ("LoadSettings" == _command.Name)
            {
                if ((null == _command.Args)
                    || (2 != _command.Args.Length)
                    || (typeof(string) != _command.Args[0].GetType())
                    || (typeof(string) != _command.Args[1].GetType()))
                {
                    System.Diagnostics.Debug.WriteLine("{0} : too few/many argument and/or bad level name and/or bad nickname argument (string type excpected).", _command.Name);
                    return false;
                }
                // load level
                this.m_levelManager.SetLocalPlayerNickname(_command.Args[1] as string);
                _command.Result = this.m_levelManager.LoadSettings(_command.Args[0] as string);
                if (null != _command.Result)
                {
                    return true;
                }
                return false;
            }
            if ("LoadLevelFromCurrentSettings" == _command.Name)
            {
                if ((null != _command.Args) && (0 != _command.Args.Length))
                {
                    System.Diagnostics.Debug.WriteLine("{0} : too many argument.", _command.Name);
                    return false;
                }
                // load level
                _command.Result = this.m_levelManager.LoadLevelFromCurrentSettings();
                if (null != _command.Result)
                {
                    // level successfully : load various related ui
                    IUIManager uiManager = this.m_coreContext.GetData<IUIManager>("UIManager");
                    uiManager.LoadScene("unittechniqueselection.xml");
                    return true;
                }
                return false;
            }
            if ("LoadFactionConfig" == _command.Name)
            {
                if ((null == _command.Args)
                    || (1 != _command.Args.Length)
                    || (typeof(string) != _command.Args[0].GetType()))
                {
                    System.Diagnostics.Debug.WriteLine("{0} : too few/many argument or bad file argument (string type excpected).", _command.Name);
                    return false;
                }
                this.m_factionManager.LoadConfig(_command.Args[0] as string);
            }
            return false;
        }

        protected void ScreenSizeChanged(int _sWidth, int _sHeight)
        {
            this.m_rendererContext.Camera.SetOrtho(_sWidth, _sHeight, 0.1f, 1000.0f);
        }

        #region IModule Membres

        public bool Load()
        {
            CoreManager coreManager = this.m_coreContext.CoreManager;

            this.m_coreContext.AddData("micivCore.Module", this);

            this.m_factionManager = new FactionManager(this.m_coreContext);
            this.m_coreContext.AddData("FactionManager", this.m_factionManager);

            this.m_levelManager = new LevelManager(this.m_coreContext);
            this.m_coreContext.AddData("LevelManager", this.m_levelManager);
            LuaManager luaManager = this.m_coreContext.GetData<LuaManager>("LuaManager");
            luaManager.State["LevelManager"] = this.m_levelManager;

            coreManager.RegisterCommandProcessor("LoadLevel", this.ProcessCommand);
            coreManager.RegisterCommandProcessor("UnloadLevel", this.ProcessCommand);
            coreManager.RegisterCommandProcessor("UpdateLevel", this.ProcessCommand);
            coreManager.RegisterCommandProcessor("LoadSettings", this.ProcessCommand);
            coreManager.RegisterCommandProcessor("LoadLevelFromCurrentSettings", this.ProcessCommand);
            coreManager.RegisterCommandProcessor("LoadFactionConfig", this.ProcessCommand);

            this.m_mapTileManager = new MapTileManager(this.m_coreContext);
            this.m_coreContext.AddData("MapTileManager", this.m_mapTileManager);

            // render context setup
            {
                // setup defaut renderer context for all things ui
                Vector2 f2ScreenSize = this.m_coreContext.GetData<Vector2>("ScreenSize");
                this.m_rendererContext = new RendererContext(this.m_coreContext);
                this.m_rendererContext.ID = "micivCore";
                this.m_rendererContext.Camera = new CameraBase(this.m_coreContext);
                this.m_rendererContext.Camera.SetOrtho(f2ScreenSize.X, f2ScreenSize.Y, 1.0f, 1000.0f);
                this.m_rendererContext.Camera.Position = new Vector3(0.0f, 0.0f, -10.0f);
                this.m_rendererContext.Camera.Rotation = new Vector3(0.0f, 0.0f, 0.0f);
                this.m_rendererContext.ScreenSizeChanged = this.ScreenSizeChanged;
                this.m_rendererContext.ClearOptions.Enabled = true;
                this.m_rendererContext.ClearOptions.Depth = 1.0f;
                this.m_rendererContext.ClearOptions.Flags = ClearFlags.ZBuffer;

                // declare created renderer context to renderer manager for automatic management
                this.m_coreContext.GetData<RendererManager>("RendererManager").AddRendererContext(this.m_rendererContext);

                // create restricted renderer contextes list for all level elements
                this.m_lstRendererContextes = new List<IRendererContext>();
                this.m_lstRendererContextes.Add(this.m_rendererContext);
            }

            return true;
        }

        public void Unload()
        {
            this.m_coreContext.RemoveData("FactionManager");
            this.m_coreContext.RemoveData("MapTileManager");
            this.m_coreContext.RemoveData("micivCore.Module");
            this.m_coreContext.RemoveData("LevelManager");

            CoreManager coreManager = this.m_coreContext.CoreManager;
            coreManager.UnregisterCommandProcessor("LoadLevel");
            coreManager.UnregisterCommandProcessor("UnloadLevel");
            coreManager.UnregisterCommandProcessor("UpdateLevel");
            coreManager.UnregisterCommandProcessor("LoadSettings");
            coreManager.UnregisterCommandProcessor("LoadLevelFromCurrentSettings");
            coreManager.UnregisterCommandProcessor("LoadFactionConfig");

            RendererManager rendererManager = this.m_coreContext.GetData<RendererManager>("RendererManager");
            rendererManager.RemoveRendererContext(this.m_rendererContext);

            LuaManager luaManager = this.m_coreContext.GetData<LuaManager>("LuaManager");
            luaManager.State["LevelManager"] = null;

            this.m_lstRendererContextes = null;
            this.m_rendererContext = null;
            this.m_factionManager = null;
            this.m_mapTileManager = null;
            this.m_levelManager = null;
        }

        #endregion
    }
}
